#include "unixhead.h"
#include <iostream>

#include <workflow/WFFacilities.h>
#include <workflow/WFHttpServer.h>

using std::cout;
using std::endl;
using std::string;

static WFFacilities::WaitGroup waitGroup(1);

void sighandler(int num)
{
    cout << "sighandler is processing" << endl;
    waitGroup.done();
}

struct SeriesContext
{
    int fd;
    char * buff;
    int size;
    protocol::HttpResponse * resp;
};

void httpCallback(WFHttpTask * serverTask)
{
    cout << "server httpCallback is running" << endl;
    auto context = (SeriesContext*)series_of(serverTask)->get_context();
    if(context) {
        delete [] context->buff;
        delete context;
    }    
}

void ioCallback(WFFileIOTask * iotask);

void process(WFHttpTask * serverTask)
{
    cout << "\nprocess funciton is running\n";
    //0.设置任务的回调函数
    serverTask->set_callback(httpCallback);

    //1. 解析请求
    auto req = serverTask->get_req();
    auto resp = serverTask->get_resp();
    string method = req->get_method();
    string uri = req->get_request_uri();
    cout << "method:" << method <<endl;
    cout << "uri:" << uri << endl;

    if(method == "GET" && uri == "/login") {
        //2. 读取本地文件postform.html
        int fd = open("/usr/local/nginx/html/postform.html", O_RDONLY);
        //char buff[1024] = {0};
        char * buff = new char[1024]();
        //int ret = read(fd, buff, sizeof(buff));
        auto fileIOTask = WFTaskFactory::create_pread_task(fd, buff, 1024, 0, ioCallback);

        //设置共享数据
        auto context = new SeriesContext();
        context->buff = buff;
        context->fd = fd;
        context->resp = resp;
        series_of(serverTask)->set_context(context);
        series_of(serverTask)->push_back(fileIOTask);
    }
}

void test0()
{
    signal(SIGINT, sighandler);
    
    WFHttpServer server(process);

    if(server.start(8888) == 0) {
        waitGroup.wait();
        server.stop();
    } else {
        cout << "server cannot start" << endl;
    }
}


int main()
{
    test0();
    return 0;
}

void ioCallback(WFFileIOTask * iotask)
{
    cout << "ioCallback is running" << endl;
    //错误检测
    int state = iotask->get_state();
    int error = iotask->get_error();
    switch(state) {
    case WFT_STATE_SYS_ERROR:
        printf("sys error: %s\n", strerror(error));break;
    case WFT_STATE_SUCCESS:
        break;
    }
    
    if(state != WFT_STATE_SUCCESS) {
        printf("Error occurs.\n");
        return;
    }

    //从哪里获取数据呢?
    auto context = (SeriesContext *)series_of(iotask)->get_context();
    context->size = iotask->get_retval();//读取了多少个字节
    cout << "context->size: " << context->size << endl;

    if(context->size > 0) {
        //3. 生成响应
        //会对buff中的内容进行复制的
        context->resp->append_output_body(context->buff, context->size);
        //设置响应报文的起始行
        context->resp->set_http_version("HTTP/1.1");
        context->resp->set_status_code("200");
        context->resp->set_reason_phrase("OK");
        //设置响应报文的首部字段
        context->resp->add_header_pair("Content-Type", "text/html");
        context->resp->add_header_pair("Content-Length", std::to_string(context->size));
    }       
    close(context->fd);
}
